package com.authine.cloudpivot.ext.applicationservice;

import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.cola.exception.Exceptions;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.data.support.SqlWithParams;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.dao.QuotationGoods;
import com.authine.cloudpivot.ext.dto.GoodsPurchaseDto;
import com.authine.cloudpivot.ext.dto.inquiry.InquiryGoodsDto;
import com.authine.cloudpivot.ext.dto.quotation.*;
import com.authine.cloudpivot.ext.dto.system.DepartmentDto;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.enums.inquiry.InquiryStatusEnum;
import com.authine.cloudpivot.ext.enums.inquiry.QuotationSourceEnum;
import com.authine.cloudpivot.ext.enums.inquiry.QuotationStatusEnum;
import com.authine.cloudpivot.ext.enums.inquiry.VendorScopeEnum;
import com.authine.cloudpivot.ext.enums.system.OrganizationAttributeEnum;
import com.authine.cloudpivot.ext.exception.InquiryException;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.message.MessageUtils;
import com.authine.cloudpivot.ext.utils.premission.PermissionUtils;
import com.authine.cloudpivot.ext.utils.system.*;
import com.authine.common.util.DateUtils;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.common.TableHelper;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.query.expression.Operator;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.dto.errorcode.ErrorCodeEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Sets;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @ClassName QuotationService
 * @Description: 我的报价
 * @Author fj
 * @Date 2021/4/28
 * @Version V1.0
 **/
@Path("QuotationService")
@Slf4j
public class QuotationService extends ApplicationService {
    private static final NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);

    /**
     * 批量参与
     *
     * @param inquiryGoodsDto 参与报价的询价商品列表
     * @return 参与成功的报价商品
     */
    @Path("batchParticipation")
    @POST
    @Operation(summary = "批量参与", tags = CUSTOM_SERVICE)
    public SingleResponse<List<BO>> batchParticipation(@Parameter InquiryGoodsDto inquiryGoodsDto) {
        SessionUser sessionUser = new SessionUser();
        Assert.notEmpty(inquiryGoodsDto.getInquiryGoodsIdList(), "询价商品id不能为空");
        // 获取用户信息
        UserDto user;
        if (!StringUtils.isEmpty(inquiryGoodsDto.getOrgId())) {
            user = UserUtils.getOrganizationAdminUser(inquiryGoodsDto.getOrgId());
        } else {
            if (!StringUtils.isEmpty(inquiryGoodsDto.getMemberId())) {
                user = UserUtils.getUserByUserId(inquiryGoodsDto.getMemberId());
            } else {
                user = sessionUser.get();
            }
        }
        DepartmentDto dept = DeptUtils.getDeptByDeptId(user.getDepartment_id().get(0).getId());

        // 获取组织信息
        OrganizationDto org = OrgUtils.getOrgByOrgId(user.getOrganization_id().get(0).getId());

        if (new HashSet<>(inquiryGoodsDto.getInquiryGoodsIdList()).size() != inquiryGoodsDto.getInquiryGoodsIdList().size()) {
            return SingleResponse.error("-1", "不能重复对一个询价商品进行参与");
        }
        
        // 当前组织不可参与报价
        if (!isItPossibleToParticipate(org, inquiryGoodsDto.getInquiryGoodsIdList())) {
            throw new BizException("当前组织不可参与报价");
        }

        List<Map<String, Object>> quotationGoodsList = Objects.requireNonNull(JdbcTemplateUtils.builder(ModelConst.T_QUOTATION_GOODS).selectField("*"))
                .in("inquiry_goods_id", inquiryGoodsDto.getInquiryGoodsIdList())
                .eq("member_id -> '$.id'", user.getId())
                .queryForList();
        log.info("------------------------根据询价商品id和当前登录人查询报价商品表，quotationGoodsList：{}------------------------", JSONObject.toJSONString(quotationGoodsList));
        if (!CollectionUtils.isEmpty(quotationGoodsList)) {
            return SingleResponse.error("-2", "不能重复参与");
        }

        // 查询询价商品进行赋值
        List<Map<String, Object>> inquiryGoodsList = Objects.requireNonNull(JdbcTemplateUtils.builder(ModelConst.T_INQUIRY_GOODS).selectField("*"))
                .in("id", inquiryGoodsDto.getInquiryGoodsIdList())
                .queryForList();
        log.info("------------------------根据询价商品id查询询价商品，inquiryGoodsList：{}------------------------", JSONObject.toJSONString(inquiryGoodsList));
        Set<String> collectSet = inquiryGoodsList.stream().filter(inquiryMap -> !String.valueOf(inquiryMap.get("inquiry_goods_status")).equals(InquiryStatusEnum.INQUIRY_GOODS_3_QUOTING.getCode())
                && "1".equals(String.valueOf(inquiryMap.get("picketaged")))).map(filterMap -> String.valueOf(filterMap.get("id"))).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(collectSet)) {
            throw new BizException("询价商品" + collectSet + "已结束询价,不可参与报价");
        }

        List<Map<String, Object>> inquiryDataList = Lists.newArrayList();
        List<BO> quotationBOList = Lists.newArrayList();
        Map<String, Object> inquiryDataMap;
        Map<String, Object> quotationDataMap;
        BigDecimal packageNum = BigDecimal.ZERO;
        String packageUnit = "";
        for (Map<String, Object> inquiryGoods : inquiryGoodsList) {
            // 通过询价商品获取询价单信息
            List<Map<String, Object>> inquiry = Objects.requireNonNull(JdbcTemplateUtils.builder(ModelConst.T_INQUIRY).selectField("*"))
                    .eq("id", inquiryGoods.get("inquiry_id"))
                    .queryForList();
            inquiryDataMap = Maps.newHashMap();
            quotationDataMap = Maps.newHashMap();
            inquiryDataMap.put("id", inquiryGoods.get("id"));
            inquiryDataMap.put("quotation_vendor_ids", inquiryGoods.get("quotation_vendor_ids") == null
                    ? org.getId() : String.valueOf(inquiryGoods.get("quotation_vendor_ids")).concat(",").concat(org.getId()));
            // todo 判断是否是虚拟供应商，先根据传参来判断
            if (inquiryGoodsDto.getIsVirtual()) {
                inquiryDataMap.put("participation", "1");
            }
            if (!StringUtils.isEmpty(inquiryGoods.get("package_num"))) {
                packageNum = new BigDecimal(String.valueOf(inquiryGoods.get("package_num")));
            }
            if (!StringUtils.isEmpty(inquiryGoods.get("package_unit"))) {
                packageUnit = String.valueOf(inquiryGoods.get("package_unit"));
            }
            // region 供应商用户、部门、组织字段
            quotationDataMap.put("client_id", inquiryGoods.get("client_id"));
            SelectorFormat platformQuotationId = new SelectorFormat();
            platformQuotationId.setType(3);
            platformQuotationId.setName(user.getUsername());
            platformQuotationId.setId(user.getId());
            quotationDataMap.put("platform_quotation_id", platformQuotationId);
            quotationDataMap.put("platform_quotation_name", user.getFullname());
            SelectorFormat vendorOrganizationId = new SelectorFormat();
            vendorOrganizationId.setType(1);
            vendorOrganizationId.setName(org.getName());
            vendorOrganizationId.setId(org.getId());
            quotationDataMap.put("vendor_organization_id", vendorOrganizationId);
            quotationDataMap.put("vendor_organization_name", org.getName());
            quotationDataMap.put("vendor_organization_description", org.getDescription());
            SelectorFormat vendorDepartmentId = new SelectorFormat();
            vendorDepartmentId.setType(1);
            vendorDepartmentId.setName(dept.getName());
            vendorDepartmentId.setId(dept.getId());
            quotationDataMap.put("vendor_department_id", vendorDepartmentId);
            quotationDataMap.put("vendor_department_name", dept.getName());
            SelectorFormat memberId = new SelectorFormat();
            memberId.setType(3);
            memberId.setName(user.getFullname());
            memberId.setId(user.getId());
            quotationDataMap.put("member_id", memberId);
            quotationDataMap.put("member_full_name", user.getFullname());
            quotationDataMap.put("user_name", user.getUsername());
            quotationDataMap.put("member_mobile", user.getCellphone());
            quotationDataMap.put("member_email", user.getEmail());
            // endregion
            quotationDataMap.put("inquiry_goods_id", inquiryGoods.get("id"));
            quotationDataMap.put("quotation_goods_status", QuotationStatusEnum.QUOTATION_0_NEW.getCode());
            // fixme 固买旧代码没有同步数据
//            quotationDataMap.put("sku", inquiryGoods.get("sku"));
//            quotationDataMap.put("inquiry_sku", inquiryGoods.get("sku"));
//            quotationDataMap.put("bar_code", inquiryGoods.get("bar_code"));
            quotationDataMap.put("name", inquiryGoods.get("name"));
            quotationDataMap.put("brand", inquiryGoods.get("brand"));
            quotationDataMap.put("model", inquiryGoods.get("model"));
            quotationDataMap.put("spec", inquiryGoods.get("spec"));
            quotationDataMap.put("num", inquiryGoods.get("num"));
            quotationDataMap.put("unit", inquiryGoods.get("unit"));
            quotationDataMap.put("package_num", packageNum);
            quotationDataMap.put("package_unit", packageUnit);
            quotationDataMap.put("auto_quotation", false);
            quotationDataMap.put("source", QuotationSourceEnum.OrdinaryQuotation.name());
            quotationDataMap.put("inquiry_name", inquiryGoods.get("inquiry_name"));
            quotationDataMap.put("inquiry_id", inquiryGoods.get("inquiry_id"));
            quotationDataMap.put("organization_company_name", inquiryGoods.get("organization_company_name"));
            quotationDataMap.put("platform_category_name", inquiryGoods.get("platform_category_name"));
            quotationDataMap.put("inquiry_time", inquiryGoods.get("createdTime"));
            quotationDataMap.put("inquiry_expire_time", inquiryGoods.get("expire"));
            quotationDataMap.put("inquiry_goods_status", inquiryGoods.get("inquiry_goods_status"));
            quotationDataMap.put("clarify_status", inquiryGoods.get("clarify_status"));
            // 税前运费默认为0
            quotationDataMap.put("pretax_freight", new BigDecimal(0));
            quotationDataMap.put("tax_rate_freight", "0.13");
            quotationDataMap.put("tax_rate", inquiry.get(0).get("quote_tax_rate_limit"));
            quotationDataMap.put("virtual_vendor", org.getVirtual());
            // 选人控件和附件设置默认值，不设置默认值数据库为空，而不是null
            quotationDataMap.put("attachment", Lists.newArrayList());
            quotationDataMap.put("clarify_attachment", Lists.newArrayList());
            quotationDataMap.put("operator", null);
            quotationDataMap.put("approval_by", null);
            // 创建报价商品
            log.info("------------------------创建报价商品数据：{}------------------------", JSONObject.toJSONString(quotationBOList));
            SingleResponse<BO> quotationCreateBO = BoServiceUtils.createBo(ModelConst.T_QUOTATION_GOODS, Collections.singletonList(quotationDataMap));
            if (!quotationCreateBO.isSuccess()) {
                Exceptions.throwBizException(ErrorCodeEnum.BO_SAVE_ERROR);
            }
            quotationBOList.add(quotationCreateBO.getData());
            inquiryDataList.add(inquiryDataMap);
        }
        // 询价商品参与次数+1
        if (!updatePartakeCount(inquiryGoodsDto.getInquiryGoodsIdList())) {
            throw new BizException("询价商品参与次数修改失败，请重新操作");
        }
        log.info("------------------------修改询价商品数据：{}------------------------", JSONObject.toJSONString(quotationBOList));
        BoServiceUtils.updateMainBo(ModelConst.T_INQUIRY_GOODS, inquiryDataList);

        // 发送消息给个人中心
        List<String> messageParams = quotationBOList.stream().map(bo -> String.format("发布了一个报价，报价单号【%s】，请查看！", bo.getBizObjectId())).collect(Collectors.toList());
        MessageUtils.createdSystemMessage(messageParams);
        return SingleResponse.of(quotationBOList);
    }

    /**
     * 更新报价商品
     *
     * @param quotationGoodsList 需要更新的报价商品
     * @return 更新后的报价商品
     */
    @Path("updateQuotation")
    @POST
    @Operation(summary = "更新报价商品", tags = CUSTOM_SERVICE)
    public SingleResponse<List<BO>> updateQuotation(@Parameter List<QuotationGoods> quotationGoodsList) {
        // todo validateQuotationGoods 校验报价商品
        Map<String, Object> quotationGoodsOld;
        Map<String, Object> inquiryGoodsMap;
        Map<String, Object> inquiryMap;
        SingleResponse<BO> quotationUpdateBO;
        SessionUser sessionUser = new SessionUser();
        // 获取组织信息
        String userId = StringUtils.isEmpty(quotationGoodsList.get(0).getUser_id()) ? sessionUser.getCurrentUserId() : quotationGoodsList.get(0).getUser_id();
        OrganizationDto org = OrgUtils.getOrgByUserId(userId);
        if (org.getSmall_scale()) {
            if (org.getSmall_scale_rate() == null) {
                throw new BizException("小规模供应商税率不能为空");
            }
        }
        List<BO> boList = Lists.newArrayList();
        try {
            for (QuotationGoods quotationGoods : quotationGoodsList) {
                quotationGoodsOld = BoServiceUtils.findListBySimple(ModelConst.T_QUOTATION_GOODS, "id", quotationGoods.getId()).getData().getData().get(0);
                log.info("------------------------通过报价商品id获取报价商品信息：{}------------------------", JSONObject.toJSONString(quotationGoodsOld));

                inquiryGoodsMap = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY_GOODS, "id", quotationGoodsOld.get("inquiry_goods_id")).getData().getData().get(0);
                log.info("------------------------通过询价商品id获取询价商品信息：{}------------------------", JSONObject.toJSONString(inquiryGoodsMap));

                inquiryMap = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY, "id", inquiryGoodsMap.get("inquiry_id")).getData().getData().get(0);
                log.info("------------------------通过询价单id获取询价单信息：{}------------------------", JSONObject.toJSONString(inquiryMap));

                int quoteMultiplePurchases = Integer.parseInt(inquiryMap.get("quote_multiple_purchases").toString());
                if (quotationGoods.getMaximum() == null && !quotationGoods.getAuto_quotation() && quoteMultiplePurchases == 0) {
                    throw new InquiryException("-1", "报价单【" + quotationGoodsOld.get("id") + "】的询价非多次购买方式,最大订货库存不能为空");
                } else if (quotationGoods.getMaximum() == null && quotationGoods.getAuto_quotation() && quoteMultiplePurchases == 0) {
                    quotationGoods.setMaximum((BigDecimal) quotationGoodsOld.get("num"));
                }
                if (quotationGoods.getMaximum() != null && quotationGoods.getMaximum().compareTo((BigDecimal) quotationGoodsOld.get("num")) < 0) {
                    throw new InquiryException("-2", "报价单【" + quotationGoodsOld.get("id") + "】的最大订货库存不可小于报价数量");
                }
                // 报价有效期不能大于366天
                Date inquiryExpire = DateUtils.parseDate(inquiryMap.get("expire").toString());
                if (StringUtils.isEmpty(quotationGoods.getExpire())) {
                    throw new InquiryException("-3", "报价有效期不能为空");
                }
                Date quotationExpire = DateUtils.parseDate(quotationGoods.getExpire());
                if (quotationExpire.getTime() - DateUtils.addDays(inquiryExpire, 366).getTime() > 0) {
                    throw new InquiryException("-4", "报价单【" + quotationGoodsOld.get("id") + "】报价有效期大于询价截止日期366天");
                }
                if ("1".equals(inquiryGoodsMap.get("item_type").toString())) {
                    if (quotationGoods.getAttachment() == null || quotationGoods.getAttachment().isEmpty()) {
                        throw new InquiryException("-5", "请上传附件");
                    }
                }
                // todo 施耐德询价校验货期不能大于询价时候的货期

                if (QuotationStatusEnum.QUOTATION_0_NEW.getCode().equals(quotationGoodsOld.get("quotation_goods_status").toString())
                        || QuotationStatusEnum.QUOTATION_2_APPROVE_NO.getCode().equals(quotationGoodsOld.get("quotation_goods_status").toString())
                        || QuotationStatusEnum.QUOTATION_4_APPROVE_BACK.getCode().equals(quotationGoodsOld.get("quotation_goods_status").toString())) {
                    if ("1".equals(inquiryGoodsMap.get("quote_edit_limit").toString())) {
                        quotationGoodsOld.put("name", quotationGoods.getName());
                        quotationGoodsOld.put("brand", quotationGoods.getBrand());
                        quotationGoodsOld.put("model", quotationGoods.getModel());
                        quotationGoodsOld.put("spec", quotationGoods.getSpec());
                        quotationGoodsOld.put("num", quotationGoods.getNum());
                        quotationGoodsOld.put("unit", quotationGoods.getUnit());
                        quotationGoodsOld.put("package_num", quotationGoods.getPackage_num());
                        quotationGoodsOld.put("package_unit", quotationGoods.getPackage_unit());
                    }
                    quotationGoodsOld.put("quotation_goods_status", QuotationStatusEnum.QUOTATION_0_NEW.getCode());
                    quotationGoodsOld.put("org_category_name", quotationGoods.getOrg_category_name());
                    quotationGoodsOld.put("auto_quotation", quotationGoods.getAuto_quotation());
                    quotationGoodsOld.put("sku", quotationGoods.getSku());
                    quotationGoodsOld.put("bar_code", quotationGoods.getBar_code());
                    quotationGoodsOld.put("delivery", quotationGoods.getDelivery() == null ? 0 : quotationGoods.getDelivery());
                    quotationGoodsOld.put("expire", quotationGoods.getExpire());
                    quotationGoodsOld.put("address", quotationGoods.getAddress());
                    quotationGoodsOld.put("description", quotationGoods.getDescription());
                    // region 报价金额
                    quotationGoodsOld.put("tax_rate", quotationGoods.getTax_rate());
                    quotationGoodsOld.put("tax_rate_freight", quotationGoods.getTax_rate_freight());
                    quotationGoodsOld.put("pretax_freight", quotationGoods.getPretax_freight());
                    quotationGoodsOld.put("pretax_price", quotationGoods.getPretax_price());
                    quotationGoodsOld.put("price", quotationGoods.getPrice());
                    quotationGoodsOld.put("pretax_total", quotationGoods.getPretax_total());
                    quotationGoodsOld.put("total", quotationGoods.getTotal());
                    quotationGoodsOld.put("amount", quotationGoods.getAmount());
                    quotationGoodsOld.put("tax_payable", quotationGoods.getTax_payable());
                    quotationGoodsOld.put("pretax_amount", quotationGoods.getPretax_amount());
                    quotationGoodsOld.put("tax_payable_freight", quotationGoods.getTax_payable_freight());
                    //平台报价运费通过手动输入
                    if ("1".equals(quotationGoodsOld.get("auto_quotation").toString())) {
                        quotationGoodsOld.put("freight", quotationGoods.getFreight());
                    }
                    // endregion
                    quotationGoodsOld.put("attachment", quotationGoods.getAttachment());
                    quotationGoodsOld.put("maximum", quotationGoods.getMaximum());
                    quotationGoodsOld.put("min_order", quotationGoods.getMin_order());
                    quotationGoodsOld.put("remarkMessage", quotationGoods.getRemark_message());
                    quotationGoodsOld.put("source", quotationGoods.getSource());

                    // 客户采购税率
                    if (org.getSmall_scale()) {
                        quotationGoodsOld.put("purchase_tax_rate", org.getSmall_scale_rate());
                    }
                    log.info("--------------quotationGoodsOld-----------：{}", JSONObject.toJSONString(quotationGoodsOld));
                    // todo 通过listBO接口查询出来的结果不能直接进行update，需要做下处理
                    quotationGoodsOld = formatQuotationGoods(quotationGoodsOld);
                    quotationUpdateBO = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS, quotationGoodsOld);
                    log.info("------------------------更新报价商品成功，更新后数据：{}------------------------", JSONObject.toJSONString(quotationUpdateBO));
                    boList.add(quotationUpdateBO.getData());
                }
            }
        } catch (InquiryException e) {
            return SingleResponse.error(e.getErrCode(), e.getErrMsg());
        }
        return SingleResponse.of(boList);
    }

    /**
     * 获取批量报价列表
     *
     * @param quotationGoodsDtoList 报价商品列表
     * @return 批量报价列表
     */
    @Path("getQuotationList")
    @POST
    @Operation(summary = "获取批量报价列表", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> getQuotationList(@Parameter List<QuotationGoodsDto> quotationGoodsDtoList) {
        Assert.notEmpty(quotationGoodsDtoList, "报价商品不能为空");
        Set<String> quotationIdSet = Sets.newHashSet();

        getQuotationIdList(quotationIdSet, quotationGoodsDtoList);

        SingleResponse<BOList> result = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", quotationIdSet);
        log.info("------------------------批量报价列表：{}------------------------", JSONObject.toJSONString(result));
        return result;
    }

    /**
     * 获取批量报价列表,不考虑整单
     *
     * @param quotationDto 报价商品列表
     * @return 批量报价列表
     */
    @Path("getQuotationListNotQuoteTotalStrategy")
    @POST
    @Operation(summary = "获取批量报价列表,不考虑整单", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> getQuotationListNotQuoteTotalStrategy(@Parameter QuotationGoodsDto quotationDto) {
        Assert.notEmpty(quotationDto.getQuotationIdList(), "报价商品id不能为空");
        BOList boList = new BOList();
        List<Map<String, Object>> quotationList = Objects.requireNonNull(JdbcTemplateUtils.builder(ModelConst.T_QUOTATION_GOODS)
                .selectField("*"))
                .in("id", quotationDto.getQuotationIdList())
                .eq("quotation_goods_status", QuotationStatusEnum.QUOTATION_0_NEW.getCode())
                .queryForList();

        log.info("------------------------通过报价商品id获取报价商品列表：{}------------------------", JSONObject.toJSONString(quotationList));
        boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
        boList.setData(quotationList == null ? Lists.newArrayList() : quotationList);
        boList.setTotal(boList.getData().size());
        return SingleResponse.of(boList);
    }

    /**
     * 批量提交
     *
     * @param quotationGoodsDtoList 请求参数
     * @return 响应结果
     */
    @Path("batchCommit")
    @POST
    @Operation(summary = "批量提交", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> batchCommit(@Parameter List<QuotationGoodsDto> quotationGoodsDtoList) {
        // 通过报价商品id获取报价商品信息
        Assert.notEmpty(quotationGoodsDtoList, "报价商品不能为空");
        List<Map<String, Object>> data = new ArrayList<>();
        List<String> inquiryGoodsIdList = new ArrayList<>();
        Map<String, Object> dataMap;
        Set<String> quotationIdSet = Sets.newHashSet();

        getQuotationIdList(quotationIdSet, quotationGoodsDtoList);

        SingleResponse<BOList> quotationList = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", quotationIdSet);
        for (Map<String, Object> quotation : quotationList.getData().getData()) {
            if (QuotationStatusEnum.QUOTATION_0_NEW.getCode().equals(quotation.get("quotation_goods_status")) ||
                    QuotationStatusEnum.QUOTATION_2_APPROVE_NO.getCode().equals(quotation.get("quotation_goods_status"))) {
                dataMap = new HashMap<>();
                inquiryGoodsIdList.add(String.valueOf(quotation.get("inquiry_goods_id")));
                // 修改状态为报价中
                dataMap.put("id", quotation.get("id"));
                dataMap.put("quotation_goods_status", QuotationStatusEnum.QUOTATION_3_QUOTED.getCode());
                data.add(dataMap);
            }
        }
        // 更新报价商品状态
        SingleResponse<BO> result = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS, data);
        log.info("------------------------更新报价商品成功，更新后数据：{}------------------------", JSONObject.toJSONString(result));
        // 修改报价次数
        if (!updateQuotationCount(inquiryGoodsIdList)) {
            throw new BizException("询价商品报价次数修改失败，请重新操作");
        }
        return result;
    }

    /**
     * 再次报价
     *
     * @param quotationDto 再次报价信息
     * @return 再次报价响应结果
     */
    @Path("counterPrice")
    @POST
    @Operation(summary = "再次报价", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> counterPrice(@Parameter QuotationGoodsDto quotationDto) {
        if (quotationDto == null || quotationDto.getQuotationIdList() == null || quotationDto.getQuotationIdList().isEmpty()) {
            return SingleResponse.error("-1", "报价商品id为空");
        }
        if (quotationDto.getPretaxPrice() == null || quotationDto.getPretaxPrice().compareTo(BigDecimal.ZERO) <= 0) {
            return SingleResponse.error("-2", "未税单价验证失败，未税单价必须大于0");
        }
        List<Map<String, Object>> quotation;
        List<Map<String, Object>> approvedHistory;
        QuotationGoods quotationGoods;
        SingleResponse<BO> quotationResult = null;
        SingleResponse<BO> approvedHistoryResult;
        StringBuilder sql = new StringBuilder();
        Map<String, Object> approvedHistoryData;
        Map<String, Object> parameter = Maps.newHashMap();
        Map<String, Object> quotationGoodsMap;
        for (String quotationId : quotationDto.getQuotationIdList()) {
            // 通过报价商品id查询报价商品信息
            quotation = BoServiceUtils.findListBySimple(ModelConst.T_QUOTATION_GOODS, "id", quotationId).getData().getData();
            if (quotation == null || quotation.isEmpty()) {
                return SingleResponse.error("-3", "数据库未查询到该报价商品");
            }
            if (!QuotationStatusEnum.QUOTATION_4_APPROVE_BACK.getCode().equals(quotation.get(0).get("quotation_goods_status"))) {
                return SingleResponse.error("-4", "只有商品状态为已还价状态才能还价");
            }
            approvedHistoryData = Maps.newHashMap();
            // 查询最近一次的还价记录
            sql.append("select id,counter_price_date from\n");
            sql.append(getTableName(ModelConst.T_QUOTATION_GOODS_APP_HIS));
            sql.append(" \n");
            sql.append("where quotation_id = :quotationId\n");
            parameter.put("quotationId", quotationId);
            sql.append("order by createdTime desc limit 1");
            log.info("sql = {}, parameters = {}", sql, JSONObject.toJSONString(parameter));
            approvedHistory = jdbcTemplate.queryForList(sql.toString(), parameter);
            // 可以无限还价，故不做判断 2021.7.9 updated by fj
//            if (((Date) approvedHistory.get(0).get("counter_price_date")).getTime() < System.currentTimeMillis()) {
//                return SingleResponse.error("-5", "还价截止日期已过，不能还价");
//            }
            // todo 重新报价失败，报价商品不在可操作权限内
            quotationGoods = new QuotationGoods();
            // 修改报价金额
            quotationGoods.setId(String.valueOf(quotation.get(0).get("id")));
            quotationGoods.setNum((BigDecimal) quotation.get(0).get("num"));
            quotationGoods.setTax_rate(String.valueOf(quotation.get(0).get("tax_rate")));
            quotationGoods.setPretax_freight((BigDecimal) quotation.get(0).get("pretax_freight"));
            quotationGoods.setPretax_price(quotationDto.getPretaxPrice());
            quotationGoods.setTax_rate_freight(String.valueOf(quotation.get(0).get("tax_rate_freight")));
            quotationGoods.setPretaxPrice(quotationGoods.getPretax_price());
            quotationGoods.setQuotation_goods_status(QuotationStatusEnum.QUOTATION_3_QUOTED.getCode());
            quotationGoodsMap = JSON.parseObject(JSON.toJSONString(quotationGoods));
            log.info("------------------------再次报价数据：{}------------------------", JSONObject.toJSONString(quotationGoodsMap));
            quotationResult = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS, quotationGoodsMap);
            log.info("------------------------再次报价成功，更新后结果：{}------------------------", JSONObject.toJSONString(quotationResult));
            // 修改还价历史记录
            approvedHistoryData.put("id", approvedHistory.get(0).get("id"));
            approvedHistoryData.put("new_quotation_price", quotationGoods.getPretax_price());
            approvedHistoryData.put("new_quotation_time", new Date());
            approvedHistoryResult = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS_APP_HIS, approvedHistoryData);
            log.info("------------------------修改还价历史记录成功，修改后结果：{}------------------------", JSONObject.toJSONString(approvedHistoryResult));
            // todo 推送还价信息
        }
        return quotationResult;
    }

    /**
     * 修改标记信息
     *
     * @param quotationDto 报价商品
     * @return 相应结果
     */
    @Path("updateRemarkMessage")
    @POST
    @Operation(summary = "修改标记信息", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> updateRemarkMessage(@Parameter QuotationGoodsDto quotationDto) {
        // 获取报价商品id
        List<Map<String, Object>> data = Lists.newArrayList();
        Map<String, Object> dataMap;
        for (String quotationId : quotationDto.getQuotationIdList()) {
            dataMap = Maps.newHashMap();
            dataMap.put("id", quotationId);
            dataMap.put("remark_message", quotationDto.getRemarkMessage());
            data.add(dataMap);
        }
        SingleResponse<BO> result = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS, data);
        log.info("------------------------result：{}------------------------", JSONObject.toJSONString(result));
        return result;
    }

    /**
     * 批量修改料号
     *
     * @param goodsPurchaseDtoList 组织采购信息
     * @return 响应结果
     */
    @Path("batchUpdateSKU")
    @POST
    @Operation(summary = "批量修改料号", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> batchUpdateSKU(@Parameter List<GoodsPurchaseDto> goodsPurchaseDtoList) {
        if (goodsPurchaseDtoList == null || goodsPurchaseDtoList.isEmpty()) {
            return SingleResponse.error("-1", "定标商品对象不能为空");
        }
        // 通过报价商品id查询组织采购表
        Map<String, Object> goodsPurchaseMap = goodsPurchaseDtoList.stream().collect(Collectors.toMap(GoodsPurchaseDto::getQuotationId, GoodsPurchaseDto::getSku));
        SingleResponse<BOList> goodsPurchaseList = BoServiceUtils.findListByIn(ModelConst.T_GOODS_PURCHASE, "quotation_goods_id", goodsPurchaseMap.keySet());
        log.info("------------------------goodsPurchaseList：{}------------------------", JSONObject.toJSONString(goodsPurchaseList));
        if (goodsPurchaseList.getData().getTotal() != goodsPurchaseMap.keySet().size()) {
            log.warn("修改企业采购目录客户sku失败：定标商品与修改的商品条数不一致；参数：{}，{}", goodsPurchaseList, goodsPurchaseDtoList);
            return SingleResponse.error("-2", "修改企业采购目录客户sku失败：定标商品与修改的商品条数不一致");
        }
        // 修改报价商品中的询价商品客户料号
        List<Map<String, Object>> quotationGoodsData = new ArrayList<>();
        Map<String, Object> quotationGoodsDataMap;
        for (GoodsPurchaseDto goodsPurchaseDto : goodsPurchaseDtoList) {
            quotationGoodsDataMap = Maps.newHashMap();
            quotationGoodsDataMap.put("id", goodsPurchaseDto.getQuotationId());
            quotationGoodsDataMap.put("inquiry_sku", goodsPurchaseDto.getSku());
            quotationGoodsData.add(quotationGoodsDataMap);
        }
        SingleResponse<BO> quotationGoodsResult = BoServiceUtils.updateMainBo(ModelConst.T_QUOTATION_GOODS, quotationGoodsData);
        log.info("------------------------quotationGoodsResult：{}------------------------", JSONObject.toJSONString(quotationGoodsResult));
        if (!quotationGoodsResult.isSuccess()) {
            return SingleResponse.error("-3", "修改报价商品客户sku失败，请重新操作");
        }

        // 修改企业采购料号
        String sku;
        List<Map<String, Object>> goodsPurchaseData = new ArrayList<>();
        Map<String, Object> goodsPurchaseDataMap;
        for (Map<String, Object> goodsPurchase : goodsPurchaseList.getData().getData()) {
            goodsPurchaseDataMap = Maps.newHashMap();
            sku = String.valueOf(goodsPurchaseMap.get(String.valueOf(goodsPurchase.get("quotation_goods_id"))));
            goodsPurchaseDataMap.put("id", goodsPurchase.get("id"));
            goodsPurchaseDataMap.put("customer_sku", sku);
            goodsPurchaseData.add(goodsPurchaseDataMap);
        }
        SingleResponse<BO> goodsPurchaseResult = BoServiceUtils.updateMainBo(ModelConst.T_GOODS_PURCHASE, goodsPurchaseData);
        log.info("------------------------goodsPurchaseResult：{}------------------------", JSONObject.toJSONString(goodsPurchaseResult));
        if (!goodsPurchaseResult.isSuccess()) {
            return SingleResponse.error("-4", "修改企业采购目录客户sku失败，请重新操作");
        }

        // 修改询价单料号
        SingleResponse<BOList> quotationList = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", goodsPurchaseMap.keySet());
        if (!quotationList.isSuccess()) {
            return SingleResponse.error("-5", "通过报价商品查询询价商品失败，请检查数据");
        }
        List<Map<String, Object>> inquiryGoodsData = Lists.newArrayList();
        Map<String, Object> inquiryGoodsDataMap;
        for (Map<String, Object> quotation : quotationList.getData().getData()) {
            inquiryGoodsDataMap = Maps.newHashMap();
            sku = String.valueOf(goodsPurchaseMap.get(String.valueOf(quotation.get("id"))));
            inquiryGoodsDataMap.put("id", quotation.get("inquiry_goods_id"));
            inquiryGoodsDataMap.put("sku", sku);
            inquiryGoodsData.add(inquiryGoodsDataMap);
        }

        SingleResponse<BO> inquiryGoodsResult = BoServiceUtils.updateMainBo(ModelConst.T_INQUIRY_GOODS, inquiryGoodsData);
        log.info("------------------------inquiryGoodsResult：{}------------------------", JSONObject.toJSONString(inquiryGoodsResult));
        return inquiryGoodsResult;
    }

    /**
     * 我的报价-待参与列表
     *
     * @param notInvolvedDto 待参与请求参数
     * @return 待参与列表
     */
    @Path("notInvolved")
    @POST
    @Operation(summary = "我的报价-待参与列表", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> notInvolved(@Parameter NotInvolvedDto notInvolvedDto) {
        // 获取组织信息(虚拟供应商参与报价时，使用的是虚拟供应商id)
        OrganizationDto org = StringUtils.isEmpty(notInvolvedDto.getVendor_id()) ? OrgUtils.getOrgByUserId() : OrgUtils.getOrgByOrgId(notInvolvedDto.getVendor_id());
        BOList boList = new BOList();
        // 获取表名
        String inquiryGoodsName = getTableName(ModelConst.T_INQUIRY_GOODS);
        Map<String, Object> parameter = Maps.newHashMap();
        // 拼接sql
        StringBuilder totalSql = new StringBuilder();// 获取总数
        StringBuilder querySql = new StringBuilder();// 查询条件
        StringBuilder listSql = new StringBuilder();// 获取结果
        totalSql.append("select count(*) as count from \n");
        querySql.append(inquiryGoodsName);
        querySql.append(" as ig \n");
        querySql.append(" left join ").append(getTableName(ModelConst.T_INQUIRY)).append(" as i on i.id = ig.inquiry_id and i.deleted = 0\n");
        querySql.append(" left join ").append(getTableName(ModelConst.T_INQUIRY_VENDOR)).append(" as iv on iv.inquiry_id = i.id and iv.deleted = 0\n");
        querySql.append("where 1 = 1\n");
        querySql.append("and ig.inquiry_goods_status = 3\n");
        querySql.append("and ig.deleted = 0\n");
        querySql.append("and (ig.quotation_vendor_ids is null or !FIND_IN_SET(:vendorId,quotation_vendor_ids))\n");
        parameter.put("vendorId", org.getId());
        // 询价方式为邀请，只有邀请的供应商才可以看到
        querySql.append("and (i.vendor_scope = :vendorScope or iv.vendor_organization_id -> '$.id' = :vendorId)\n");
        parameter.put("vendorScope", VendorScopeEnum.ALL.getCode());
        parameter.put("vendorId", org.getId());
        // 牧原组织
        if (!StringUtils.isEmpty(notInvolvedDto.getEquals_organization_company_name())) {
            querySql.append("and ig.organization_company_name = :equalsOrganizationCompanyName\n");
            parameter.put("equalsOrganizationCompanyName", notInvolvedDto.getEquals_organization_company_name());
        }
        // 非牧原组织
        if (!StringUtils.isEmpty(notInvolvedDto.getNot_equals_organization_company_name())) {
            querySql.append("and ig.organization_company_name != :notEqualsOrganizationCompanyName\n");
            parameter.put("notEqualsOrganizationCompanyName", notInvolvedDto.getNot_equals_organization_company_name());
        }
        // 商品编号
        if (!StringUtils.isEmpty(notInvolvedDto.getId())) {
            String[] ids = notInvolvedDto.getId().split(";");
            querySql.append("and ig.id in (:id)\n");
            parameter.put("id", Arrays.asList(ids));
        }
        // 报价次数
        if (notInvolvedDto.getQuote_count() != null) {
            querySql.append("and ig.quote_count = :quoteCount\n");
            parameter.put("quoteCount", notInvolvedDto.getQuote_count());
        }
        // 参与次数
        if (notInvolvedDto.getPartake_count() != null) {
            querySql.append("and ig.partake_count = :partakeCount\n");
            parameter.put("partakeCount", notInvolvedDto.getPartake_count());
        }
        // 询价单号
        if (!StringUtils.isEmpty(notInvolvedDto.getInquiry_id())) {
            querySql.append("and ig.inquiry_id = :inquiryId\n");
            parameter.put("inquiryId", notInvolvedDto.getInquiry_id());
        }
        // 商品名称
        if (!StringUtils.isEmpty(notInvolvedDto.getName())) {
            querySql.append("and ig.name like :name\n");
            parameter.put("name", "%".concat(notInvolvedDto.getName()).concat("%"));
        }
        // 品牌
        if (!StringUtils.isEmpty(notInvolvedDto.getBrand())) {
            querySql.append("and ig.brand like :brand\n");
            parameter.put("brand", "%".concat(notInvolvedDto.getBrand()).concat("%"));
        }
        // 型号
        if (!StringUtils.isEmpty(notInvolvedDto.getModel())) {
            querySql.append("and ig.model like :model\n");
            parameter.put("model", "%".concat(notInvolvedDto.getModel()).concat("%"));
        }
        // 标题
        if (!StringUtils.isEmpty(notInvolvedDto.getInquiry_name())) {
            querySql.append("and ig.inquiry_name like :inquiryName\n");
            parameter.put("inquiryName", "%".concat(notInvolvedDto.getInquiry_name()).concat("%"));
        }
        // 客户组织
        if (!StringUtils.isEmpty(notInvolvedDto.getOrganization_company_name())) {
            querySql.append("and ig.organization_company_name like :organizationCompanyName\n");
            parameter.put("organizationCompanyName", "%".concat(notInvolvedDto.getOrganization_company_name()).concat("%"));
        }
        // 分类
        if (!StringUtils.isEmpty(notInvolvedDto.getPlatform_category_name())) {
            querySql.append("and ig.platform_category_name = :platformCategoryName\n");
            parameter.put("platformCategoryName", notInvolvedDto.getPlatform_category_name());
        }
        // 收货地址
        if (!StringUtils.isEmpty(notInvolvedDto.getAddress())) {
            querySql.append("and ig.address like :address\n");
            parameter.put("address", "%".concat(notInvolvedDto.getAddress()).concat("%"));
        }
        // 询价发布日期
        if (!CollectionUtils.isEmpty(notInvolvedDto.getCreatedTime())) {
            querySql.append("and ig.createdTime BETWEEN :createdStartTime and :createdEndTime\n");
            parameter.put("createdStartTime", notInvolvedDto.getCreatedTime().get(0));
            parameter.put("createdEndTime", notInvolvedDto.getCreatedTime().get(1));
        }
        // 询价截止时间
        if (!CollectionUtils.isEmpty(notInvolvedDto.getExpire())) {
            querySql.append("and ig.expire BETWEEN :expireStartTime and :expireEndTime\n");
            parameter.put("expireStartTime", notInvolvedDto.getExpire().get(0));
            parameter.put("expireEndTime", notInvolvedDto.getExpire().get(1));
        } else {
            querySql.append("and ig.expire > :expire\n");
            parameter.put("expire", new Date());
        }
        // 拼接权限sql
//        SqlWithParams inquiryGoodsPermissionSql = PermissionUtils.permissionSql(ModelConst.T_INQUIRY, ModelConst.T_INQUIRY_GOODS, "ig");
//        log.info("-----------------------询价商品权限sql：{}------------------------", JSONObject.toJSONString(inquiryGoodsPermissionSql));
//        if (inquiryGoodsPermissionSql != null && !StringUtils.isEmpty(inquiryGoodsPermissionSql.getSql())) {
//            querySql.append("and ");
//            querySql.append(inquiryGoodsPermissionSql.getSql());
//            querySql.append("\n");
//            parameter.putAll(inquiryGoodsPermissionSql.getParams());
//        }

        // OrganizationAttributeEnum.INQUIRY_INVITED。仅邀请组织可报价，在批量参与时做判断，邀请供应商也可以看到所有数据
        boolean enabledParticiptionInvited = OrgAttributeUtils.isEnabledAttribute(org.getId(), OrganizationAttributeEnum.PARTICIPTION_INVITED);
        // 只查看邀请组织的数据
        if (enabledParticiptionInvited) {
            // 获取所有客户信息
            List<String> customerIdListByVendorId = OrgUtils.listCustomerByVendorId(org.getId());
            List<String> customerAllList = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(customerIdListByVendorId)) {
                customerIdListByVendorId.forEach(customerId -> {
                    // 根据组织id获取集团下所有组织
                    List<OrganizationDto> customerIdListByParentId = OrgUtils.getOrgListByOrgId(customerId);
                    customerAllList.addAll(customerIdListByParentId.stream().map(OrganizationDto :: getId).collect(Collectors.toList()));
                });
            }
            if (!CollectionUtils.isEmpty(customerAllList)) {
                querySql.append("and CASE WHEN JSON_VALID( i.organization_id ) THEN JSON_UNQUOTE(i.organization_id -> '$.id') in (:customerIdList)\n");
                querySql.append("ELSE NULL END\n");
                parameter.put("customerIdList", customerAllList);
            }
        }
        totalSql.append(querySql);
        log.info("totalSql = {}, parameters = {}", totalSql, JSONObject.toJSONString(parameter));
        // 获取列表总数
        Integer count;
        try {
            count = jdbcTemplate.queryForObject(totalSql.toString(), parameter, Integer.class);
            if (count == null) {
                count = 0;
            }
        } catch (DataAccessException e) {
            e.printStackTrace();
            count = 0;
        }
        if (count == 0) {
            boList.setSchemaCode(ModelConst.T_INQUIRY_GOODS);
            boList.setTotal(count);
            return SingleResponse.of(boList);
        }
        listSql.append("select ig.* from \n");
        listSql.append(querySql);
        listSql.append("group by ig.id\n");
        listSql.append("order by ig.createdTime desc\n");
        String limit = String.format(" limit %s,%s", (notInvolvedDto.getPageIndex() - 1) * notInvolvedDto.getPageSize(), notInvolvedDto.getPageSize());
        listSql.append(limit);
        log.info("listSql = {}, parameters = {}", listSql, JSONObject.toJSONString(parameter));
        List<Map<String, Object>> result = jdbcTemplate.queryForList(listSql.toString(), parameter);
        // 对结果进行格式化
        BoResultFormat.resultFormat(result, ModelConst.T_INQUIRY_GOODS, true);
        log.info("result = {}", JSONObject.toJSONString(result));
        boList.setData(result);
        boList.setSchemaCode(ModelConst.T_INQUIRY_GOODS);
        boList.setTotal(count);
        log.info("------------------------我的报价-待参与列表返回结果：{}------------------------", JSONObject.toJSONString(SingleResponse.of(boList)));
        return SingleResponse.of(boList);
    }

    /**
     * 我的报价-待报价列表
     *
     * @param quotationGoodsListDto 查询条件
     * @return 响应结果
     */
    @Path("quotationGoodsList")
    @POST
    @Operation(summary = "我的报价-待报价列表", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> quotationGoodsList(@Parameter QuotationGoodsListDto quotationGoodsListDto) {
        BOList boList = new BOList();
        // 获取表名
        String inquiryName = getTableName(ModelConst.T_INQUIRY);
        String inquiryGoodsName = getTableName(ModelConst.T_INQUIRY_GOODS);
        String quotationGoodsName = getTableName(ModelConst.T_QUOTATION_GOODS);
        Map<String, Object> parameter = Maps.newHashMap();
        // 拼接sql
        StringBuilder totalSql = new StringBuilder();// 获取总数
        StringBuilder querySql = new StringBuilder();// 查询条件
        StringBuilder listSql = new StringBuilder();// 获取结果
        totalSql.append("select count(*) as count from \n");
        querySql.append(quotationGoodsName).append(" as qg \n");
        querySql.append("LEFT OUTER JOIN ").append(inquiryGoodsName).append(" ig ON qg.inquiry_goods_id = ig.id\n");
        querySql.append("LEFT OUTER JOIN ").append(inquiryName).append(" i ON qg.inquiry_id = i.id\n");
        querySql.append("where 1 = 1\n");
        querySql.append("and qg.deleted = 0\n");
        querySql.append("and qg.quotation_goods_status = 0\n");
        querySql.append("and i.deleted = 0\n");
        // 商品编号
        if (!StringUtils.isEmpty(quotationGoodsListDto.getId())) {
            String[] ids = quotationGoodsListDto.getId().split(";");
            querySql.append("and qg.id in (:id)\n");
            parameter.put("id", Arrays.asList(ids));
        }
        // 报价次数
        if (!CollectionUtils.isEmpty(quotationGoodsListDto.getQuote_count())) {
            if (quotationGoodsListDto.getQuote_count().get(0) != null) {
                querySql.append("and ig.quote_count >= :quoteCountStart\n");
                parameter.put("quoteCountStart", quotationGoodsListDto.getQuote_count().get(0));
            }
            if (quotationGoodsListDto.getQuote_count().get(1) != null) {
                querySql.append("and ig.quote_count <= :quoteCountEnd\n");
                parameter.put("quoteCountEnd", quotationGoodsListDto.getQuote_count().get(1));
            }
        }
        // 参与次数
        if (!StringUtils.isEmpty(quotationGoodsListDto.getPartake_count())) {
            querySql.append("and ig.partake_count = :partakeCount\n");
            parameter.put("partakeCount", quotationGoodsListDto.getPartake_count());
        }
        // 询价单号
        if (!StringUtils.isEmpty(quotationGoodsListDto.getInquiry_id())) {
            querySql.append("and ig.inquiry_id = :inquiryId\n");
            parameter.put("inquiryId", quotationGoodsListDto.getInquiry_id());
        }
        // 询价商品状态
        if (!StringUtils.isEmpty(quotationGoodsListDto.getInquiry_goods_status())) {
            querySql.append("and ig.inquiry_goods_status = :inquiryGoodsStatus\n");
            parameter.put("inquiryGoodsStatus", quotationGoodsListDto.getInquiry_goods_status());
        }
        // 澄清状态
        if (!StringUtils.isEmpty(quotationGoodsListDto.getClarify_status())) {
            querySql.append("and ig.clarify_status = :clarifyStatus\n");
            parameter.put("clarifyStatus", quotationGoodsListDto.getClarify_status());
        }
        // 商品名称
        if (!StringUtils.isEmpty(quotationGoodsListDto.getName())) {
            querySql.append("and qg.name like :name\n");
            parameter.put("name", "%".concat(quotationGoodsListDto.getName()).concat("%"));
        }
        // 品牌
        if (!StringUtils.isEmpty(quotationGoodsListDto.getBrand())) {
            querySql.append("and qg.brand like :brand\n");
            parameter.put("brand", "%".concat(quotationGoodsListDto.getBrand()).concat("%"));
        }
        // 型号
        if (!StringUtils.isEmpty(quotationGoodsListDto.getModel())) {
            querySql.append("and qg.model like :model\n");
            parameter.put("model", "%".concat(quotationGoodsListDto.getModel()).concat("%"));
        }
        // 标题
        if (!StringUtils.isEmpty(quotationGoodsListDto.getInquiry_name())) {
            querySql.append("and ig.inquiry_name like :inquiryName\n");
            parameter.put("inquiryName", "%".concat(quotationGoodsListDto.getInquiry_name()).concat("%"));
        }
        // 客户组织
        if (!StringUtils.isEmpty(quotationGoodsListDto.getOrganization_company_name())) {
            querySql.append("and ig.organization_company_name like :organizationCompanyName\n");
            parameter.put("organizationCompanyName", "%".concat(quotationGoodsListDto.getOrganization_company_name()).concat("%"));
        }
        // 供应商组织
        if (!StringUtils.isEmpty(quotationGoodsListDto.getVendor_organization_name())) {
            querySql.append("and qg.vendor_organization_name like :vendorOrganizationName\n");
            parameter.put("vendorOrganizationName", "%".concat(quotationGoodsListDto.getVendor_organization_name()).concat("%"));
        }
        // 分类
        if (!StringUtils.isEmpty(quotationGoodsListDto.getPlatform_category_name())) {
            querySql.append("and ig.platform_category_name = :platformCategoryName\n");
            parameter.put("platformCategoryName", quotationGoodsListDto.getPlatform_category_name());
        }
        // 询价发布日期
        if (!CollectionUtils.isEmpty(quotationGoodsListDto.getInquiry_time())) {
            querySql.append("and ig.createdTime BETWEEN :createdStartTime and :createdEndTime\n");
            parameter.put("createdStartTime", quotationGoodsListDto.getInquiry_time().get(0));
            parameter.put("createdEndTime", quotationGoodsListDto.getInquiry_time().get(1));
        }
        // 询价截止时间
        if (!CollectionUtils.isEmpty(quotationGoodsListDto.getInquiry_expire_time())) {
            querySql.append("and ig.expire BETWEEN :expireStartTime and :expireEndTime\n");
            parameter.put("expireStartTime", quotationGoodsListDto.getInquiry_expire_time().get(0));
            parameter.put("expireEndTime", quotationGoodsListDto.getInquiry_expire_time().get(1));
        } else {
            querySql.append("and ig.expire > :expire\n");
            parameter.put("expire", new Date());
        }
        // 拼接权限sql
        SqlWithParams quotationGoodsPermissionSql = PermissionUtils.permissionSql(ModelConst.T_QUOTATION_GOODS, ModelConst.T_QUOTATION_GOODS, "qg");
        log.info("------------------------报价商品权限sql：{}------------------------", JSONObject.toJSONString(quotationGoodsPermissionSql));
        if (quotationGoodsPermissionSql != null && !StringUtils.isEmpty(quotationGoodsPermissionSql.getSql())) {
            querySql.append("and ").append(quotationGoodsPermissionSql.getSql()).append(" \n");
            parameter.putAll(quotationGoodsPermissionSql.getParams());
        }
        totalSql.append(querySql);
        log.info("totalSql = {}, parameters = {}", totalSql, JSONObject.toJSONString(parameter));
        // 获取列表总数
        Integer count;
        try {
            count = jdbcTemplate.queryForObject(totalSql.toString(), parameter, Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
            count = 0;
        }
        if (count == null || count == 0) {
            boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
            boList.setTotal(0);
            return SingleResponse.of(boList);
        }
        listSql.append("select qg.* from \n");
        listSql.append(querySql);
        listSql.append("order by createdTime desc");
        String limit = String.format(" limit %s,%s", (quotationGoodsListDto.getPageIndex() - 1) * quotationGoodsListDto.getPageSize(), quotationGoodsListDto.getPageSize());
        listSql.append(limit);
        log.info("listSql = {}, parameters = {}", listSql, JSONObject.toJSONString(parameter));
        List<Map<String, Object>> result = jdbcTemplate.queryForList(listSql.toString(), parameter);
        log.info("------------------------我的报价-待报价列表返回结果：{}------------------------", result);
        // 对结果进行格式化
        BoResultFormat.resultFormat(result, ModelConst.T_QUOTATION_GOODS, true);
        boList.setData(result);
        boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
        boList.setTotal(count);
        return SingleResponse.of(boList);
    }

    /**
     * 我的报价-已报价列表
     *
     * @param quotedListDto 查询条件
     * @return 响应结果
     */
    @Path("quotedList")
    @POST
    @Operation(summary = "我的报价-已报价列表", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> quotedList(@Parameter QuotedListDto quotedListDto) {
        BOList boList = new BOList();
        // 获取表名
        String quotationGoodsName = getTableName(ModelConst.T_QUOTATION_GOODS);
        Map<String, Object> parameter = Maps.newHashMap();
        // 拼接sql
        StringBuilder totalSql = new StringBuilder();// 获取总数
        StringBuilder querySql = new StringBuilder();// 查询条件
        StringBuilder listSql = new StringBuilder();// 获取结果
        totalSql.append("select count(*) as count from \n");
        querySql.append(quotationGoodsName).append(" as qg \n");
        querySql.append("where 1 = 1\n");
        querySql.append("and qg.quotation_goods_status = 3\n");
        querySql.append("and qg.deleted = 0\n");
        querySql.append("and qg.price is not null\n");
        // 编号
        if (!StringUtils.isEmpty(quotedListDto.getId())) {
            String[] ids = quotedListDto.getId().split(";");
            querySql.append("and qg.id in (:id)\n");
            parameter.put("id", Arrays.asList(ids));
        }
        // 询价单号
        if (!StringUtils.isEmpty(quotedListDto.getInquiry_id())) {
            querySql.append("and qg.inquiry_id = :inquiryId\n");
            parameter.put("inquiryId", quotedListDto.getInquiry_id());
        }
        // 商品名称
        if (!StringUtils.isEmpty(quotedListDto.getName())) {
            querySql.append("and qg.name like :name\n");
            parameter.put("name", "%".concat(quotedListDto.getName()).concat("%"));
        }
        // 品牌
        if (!StringUtils.isEmpty(quotedListDto.getBrand())) {
            querySql.append("and qg.brand like :brand\n");
            parameter.put("brand", "%".concat(quotedListDto.getBrand()).concat("%"));
        }
        // 型号
        if (!StringUtils.isEmpty(quotedListDto.getModel())) {
            querySql.append("and qg.model like :model\n");
            parameter.put("model", "%".concat(quotedListDto.getModel()).concat("%"));
        }
        // 标题
        if (!StringUtils.isEmpty(quotedListDto.getInquiry_name())) {
            querySql.append("and qg.inquiry_name like :inquiryName\n");
            parameter.put("inquiryName", "%".concat(quotedListDto.getInquiry_name()).concat("%"));
        }
        // 客户组织
        if (!StringUtils.isEmpty(quotedListDto.getOrganization_company_name())) {
            querySql.append("and qg.organization_company_name like :organizationCompanyName\n");
            parameter.put("organizationCompanyName", "%".concat(quotedListDto.getOrganization_company_name()).concat("%"));
        }
        // 供应商组织
        if (!StringUtils.isEmpty(quotedListDto.getVendor_organization_name())) {
            querySql.append("and qg.vendor_organization_name like :vendorOrganizationName\n");
            parameter.put("vendorOrganizationName", "%".concat(quotedListDto.getVendor_organization_name()).concat("%"));
        }
        // 分类
        if (!StringUtils.isEmpty(quotedListDto.getPlatform_category_name())) {
            querySql.append("and qg.platform_category_name = :platformCategoryName\n");
            parameter.put("platformCategoryName", quotedListDto.getPlatform_category_name());
        }
        // 询价发布日期
        if (!CollectionUtils.isEmpty(quotedListDto.getInquiry_time())) {
            querySql.append("and qg.inquiry_time BETWEEN :createdStartTime and :createdEndTime\n");
            parameter.put("createdStartTime", quotedListDto.getInquiry_time().get(0));
            parameter.put("createdEndTime", quotedListDto.getInquiry_time().get(1));
        }
        // 拼接权限sql
        SqlWithParams quotationGoodsPermissionSql = PermissionUtils.permissionSql(ModelConst.T_QUOTATION_GOODS, ModelConst.T_QUOTATION_GOODS, "qg");
        log.info("------------------------询价单权限sql：{}------------------------", JSONObject.toJSONString(quotationGoodsPermissionSql));
        if (quotationGoodsPermissionSql != null && !StringUtils.isEmpty(quotationGoodsPermissionSql.getSql())) {
            querySql.append("and ").append(quotationGoodsPermissionSql.getSql()).append(" \n");
            parameter.putAll(quotationGoodsPermissionSql.getParams());
        }
        totalSql.append(querySql);
        log.info("totalSql = {}, parameters = {}", totalSql, JSONObject.toJSONString(parameter));
        // 获取列表总数
        Integer count;
        try {
            count = jdbcTemplate.queryForObject(totalSql.toString(), parameter, Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
            count = 0;
        }
        if (count == null || count == 0) {
            boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
            boList.setTotal(0);
            return SingleResponse.of(boList);
        }
        listSql.append("select qg.* from \n");
        listSql.append(querySql);
        listSql.append("order by createdTime desc");
        String limit = String.format(" limit %s,%s", (quotedListDto.getPageIndex() - 1) * quotedListDto.getPageSize(), quotedListDto.getPageSize());
        listSql.append(limit);
        log.info("listSql = {}, parameters = {}", listSql, JSONObject.toJSONString(parameter));
        List<Map<String, Object>> result = jdbcTemplate.queryForList(listSql.toString(), parameter);
        log.info("------------------------我的报价-已报价列表返回结果：{}------------------------", result);
        // 对结果进行格式化
        BoResultFormat.resultFormat(result, ModelConst.T_QUOTATION_GOODS, true);
        boList.setData(result);
        boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
        boList.setTotal(count);
        return SingleResponse.of(boList);
    }

    /**
     * 我的报价-已还价
     *
     * @param approveBackListDto 查询条件
     * @return 返回结果
     */
    @Path("approveBackList")
    @POST
    @Operation(summary = "我的报价-已还价", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> approveBackList(@Parameter ApproveBackListDto approveBackListDto) {
        BOList boList = new BOList();
        // 获取表名
        String quotationGoodsName = getTableName(ModelConst.T_QUOTATION_GOODS);
        Map<String, Object> parameter = Maps.newHashMap();
        // 拼接sql
        StringBuilder totalSql = new StringBuilder();// 获取总数
        StringBuilder querySql = new StringBuilder();// 查询条件
        StringBuilder listSql = new StringBuilder();// 获取结果
        totalSql.append("select count(*) as count from \n");
        querySql.append(quotationGoodsName).append(" as qg \n");
        querySql.append("where 1 = 1\n");
        querySql.append("and qg.quotation_goods_status = 4\n");
        querySql.append("and qg.deleted = 0\n");
        querySql.append("and qg.price is not null\n");
        // 编号
        if (!StringUtils.isEmpty(approveBackListDto.getId())) {
            String[] ids = approveBackListDto.getId().split(";");
            querySql.append("and qg.id in (:id)\n");
            parameter.put("id", Arrays.asList(ids));
        }
        // 询价单号
        if (!StringUtils.isEmpty(approveBackListDto.getInquiry_id())) {
            querySql.append("and qg.inquiry_id = :inquiryId\n");
            parameter.put("inquiryId", approveBackListDto.getInquiry_id());
        }
        // 商品名称
        if (!StringUtils.isEmpty(approveBackListDto.getName())) {
            querySql.append("and qg.name like :name\n");
            parameter.put("name", "%".concat(approveBackListDto.getName()).concat("%"));
        }
        // 品牌
        if (!StringUtils.isEmpty(approveBackListDto.getBrand())) {
            querySql.append("and qg.brand like :brand\n");
            parameter.put("brand", "%".concat(approveBackListDto.getBrand()).concat("%"));
        }
        // 型号
        if (!StringUtils.isEmpty(approveBackListDto.getModel())) {
            querySql.append("and qg.model like :model\n");
            parameter.put("model", "%".concat(approveBackListDto.getModel()).concat("%"));
        }
        // 标题
        if (!StringUtils.isEmpty(approveBackListDto.getInquiry_name())) {
            querySql.append("and qg.inquiry_name like :inquiryName\n");
            parameter.put("inquiryName", "%".concat(approveBackListDto.getInquiry_name()).concat("%"));
        }
        // 客户组织
        if (!StringUtils.isEmpty(approveBackListDto.getOrganization_company_name())) {
            querySql.append("and qg.organization_company_name like :organizationCompanyName\n");
            parameter.put("organizationCompanyName", "%".concat(approveBackListDto.getOrganization_company_name()).concat("%"));
        }
        // 供应商组织
        if (!StringUtils.isEmpty(approveBackListDto.getVendor_organization_name())) {
            querySql.append("and qg.vendor_organization_name like :vendorOrganizationName\n");
            parameter.put("vendorOrganizationName", "%".concat(approveBackListDto.getVendor_organization_name()).concat("%"));
        }
        // 分类
        if (!StringUtils.isEmpty(approveBackListDto.getPlatform_category_name())) {
            querySql.append("and qg.platform_category_name = :platformCategoryName\n");
            parameter.put("platformCategoryName", approveBackListDto.getPlatform_category_name());
        }
        // 询价截止日期
        if (!CollectionUtils.isEmpty(approveBackListDto.getInquiry_expire_time())) {
            querySql.append("and qg.inquiry_expire_time BETWEEN :expireStartTime and :expiredEndTime\n");
            parameter.put("expireStartTime", approveBackListDto.getInquiry_expire_time().get(0));
            parameter.put("expiredEndTime", approveBackListDto.getInquiry_expire_time().get(1));
        }
        // 拼接权限sql
        SqlWithParams quotationGoodsPermissionSql = PermissionUtils.permissionSql(ModelConst.T_QUOTATION_GOODS, ModelConst.T_QUOTATION_GOODS, "qg");
        log.info("------------------------报价商品权限sql：{}------------------------", JSONObject.toJSONString(quotationGoodsPermissionSql));
        if (quotationGoodsPermissionSql != null && !StringUtils.isEmpty(quotationGoodsPermissionSql.getSql())) {
            querySql.append("and ").append(quotationGoodsPermissionSql.getSql()).append(" \n");
            parameter.putAll(quotationGoodsPermissionSql.getParams());
        }
        totalSql.append(querySql);
        log.info("totalSql = {}, parameters = {}", totalSql, JSONObject.toJSONString(parameter));
        // 获取列表总数
        Integer count;
        try {
            count = jdbcTemplate.queryForObject(totalSql.toString(), parameter, Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
            count = 0;
        }
        if (count == null || count == 0) {
            boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
            boList.setTotal(0);
            return SingleResponse.of(boList);
        }
        listSql.append("select qg.* from \n");
        listSql.append(querySql);
        listSql.append("order by createdTime desc");
        String limit = String.format(" limit %s,%s", (approveBackListDto.getPageIndex() - 1) * approveBackListDto.getPageSize(), approveBackListDto.getPageSize());
        listSql.append(limit);
        log.info("listSql = {}, parameters = {}", listSql, JSONObject.toJSONString(parameter));
        List<Map<String, Object>> result = jdbcTemplate.queryForList(listSql.toString(), parameter);
        log.info("------------------------我的报价-已还价列表返回结果：{}------------------------", result);
        // 对结果进行格式化
        BoResultFormat.resultFormat(result, ModelConst.T_QUOTATION_GOODS, true);
        boList.setData(result);
        boList.setSchemaCode(ModelConst.T_QUOTATION_GOODS);
        boList.setTotal(count);
        return SingleResponse.of(boList);
    }

    /**
     * 报价金额计算
     *
     * @param quotationGoodsDto 报价金额
     * @return 响应结果
     */
    @Path("amountCalculation")
    @POST
    @Operation(summary = "报价金额计算", tags = CUSTOM_SERVICE)
    public SingleResponse<QuotationGoods> amountCalculation(@Parameter QuotationGoodsDto quotationGoodsDto) {
        if (quotationGoodsDto.getPretaxPrice() == null && !quotationGoodsDto.isVatQuotation()) {
            return SingleResponse.error("-1", "未税单价不能为空");
        }
        if (quotationGoodsDto.getNum() == null) {
            return SingleResponse.error("-2", "数量不能为空");
        }
        if (quotationGoodsDto.getTaxRate() == null) {
            return SingleResponse.error("-3", "税率不能为空");
        }
        if (quotationGoodsDto.getPretaxFreight() == null) {
            return SingleResponse.error("-4", "税前运费不能为空");
        }
        if (quotationGoodsDto.getTaxRateFreight() == null) {
            return SingleResponse.error("-5", "运费税率不能为空");
        }
        if (quotationGoodsDto.getPrice() == null && quotationGoodsDto.isVatQuotation()) {
            return SingleResponse.error("-6", "含税单价不能为空");
        }
        QuotationGoods quotationGoods = new QuotationGoods();
        // 客户开启含税报价，需要先根据含税计算未税
        if (quotationGoodsDto.isVatQuotation()) {
            BigDecimal pretaxPrice = BigDecimalUtils.calculateTaxBefore(quotationGoodsDto.getPrice(), quotationGoodsDto.getTaxRate());

            quotationGoods.setPretax_price(pretaxPrice);
        } else {
            quotationGoods.setPretax_price(quotationGoodsDto.getPretaxPrice());
        }
        quotationGoods.setNum(quotationGoodsDto.getNum());
        quotationGoods.setTax_rate(quotationGoodsDto.getTaxRate().toPlainString());
        quotationGoods.setPretax_freight(quotationGoodsDto.getPretaxFreight());
        quotationGoods.setTax_rate_freight(quotationGoodsDto.getTaxRateFreight().toPlainString());
        quotationGoods.setPretaxPrice(quotationGoods.getPretax_price());
        return SingleResponse.of(quotationGoods);
    }

    /**
     * 客户是否需要含税报价
     *
     * @param orgParam 组织名称
     * @return 响应结果
     */
    @Path("isVatQuotation")
    @POST
    @Operation(summary = "客户是否需要含税报价", tags = CUSTOM_SERVICE)
    public boolean isVatQuotation(@Parameter OrganizationDto orgParam) {
        // 根据组织名称获取组织信息
        OrganizationDto org = OrgUtils.getOrgByOrgName(orgParam.getName());
        return OrgAttributeUtils.isEnabledAttribute(org.getId(), OrganizationAttributeEnum.VAT_QUOTATION);
    }

    /**
     * 报价商品更新前，对listBO查询出来的数据做格式化处理
     *
     * @param quotationGoodsOld 报价商品
     * @return 格式化后的报价商品
     */
    public Map<String, Object> formatQuotationGoods(Map<String, Object> quotationGoodsOld) {
        quotationGoodsOld.remove("createdBy");
        quotationGoodsOld.remove("createdDept");
        quotationGoodsOld.remove("owner");
        quotationGoodsOld.remove("ownerDept");
        quotationGoodsOld.remove("modifiedBy");
        // 更新时不操作人员、组织、部门
        quotationGoodsOld.remove("member_id");
        quotationGoodsOld.remove("platform_quotation_id");
        quotationGoodsOld.remove("vendor_department_id");
        quotationGoodsOld.remove("vendor_organization_id");
        quotationGoodsOld.put("deleted", "1".equals(String.valueOf(quotationGoodsOld.get("deleted"))));
        quotationGoodsOld.put("virtual_vendor", "1".equals(String.valueOf(quotationGoodsOld.get("virtual_vendor"))));
        quotationGoodsOld.put("picketage", "1".equals(String.valueOf(quotationGoodsOld.get("picketage"))));
        quotationGoodsOld.put("clarify_attachment", Lists.newArrayList());
        return quotationGoodsOld;
    }

    /**
     * 通过领域模型获取完整表名称
     *
     * @param schemaCode 模型编码
     * @return 表名
     */
    private String getTableName(String schemaCode) {
        return ApplicationContextUtils.getBean(TableHelper.class).getTableName(schemaCode);
    }

    /**
     * 修改询价商品的参与次数
     *
     * @param inquiryGoodsIdList 询价商品id
     */
    private boolean updatePartakeCount(List<String> inquiryGoodsIdList) {
        boolean result = true;
        StringBuilder builder;
        Map<String, Object> parameter = Maps.newHashMap();
        parameter.put("deleted", 0);
        parameter.put("status", Arrays.asList(QuotationStatusEnum.QUOTATION_0_NEW.getCode()
                , QuotationStatusEnum.QUOTATION_1_APPROVE.getCode(), QuotationStatusEnum.QUOTATION_2_APPROVE_NO.getCode()
                , QuotationStatusEnum.QUOTATION_3_QUOTED.getCode(), QuotationStatusEnum.QUOTATION_4_APPROVE_BACK.getCode()));
        for (String inquiryGoodsId : inquiryGoodsIdList) {
            builder = new StringBuilder();
            builder.append("update\n")
                    .append(getTableName(ModelConst.T_INQUIRY_GOODS)).append("\n")
                    .append("set partake_count = \n")
                    .append("(select count(*) from\n")
                    .append(getTableName(ModelConst.T_QUOTATION_GOODS)).append("\n")
                    .append("where 1 = 1\n")
                    .append("and deleted = :deleted\n")
                    .append("and inquiry_goods_id = :inquiryGoodsId\n")
                    .append("and quotation_goods_status in (:status))\n")
                    .append("where id = :inquiryGoodsId\n");
            parameter.put("inquiryGoodsId", inquiryGoodsId);
            log.info("sql = {}, parameters = {}", builder, JSONObject.toJSONString(parameter));
            if (jdbcTemplate.update(builder.toString(), parameter) != 1) {
                result = false;
                break;
            }
        }
        return result;
    }

    /**
     * 修改询价商品的报价次数
     *
     * @param inquiryGoodsIdList 询价商品id
     */
    private boolean updateQuotationCount(List<String> inquiryGoodsIdList) {
        boolean result = true;
        StringBuilder builder;
        Map<String, Object> parameter = Maps.newHashMap();
        parameter.put("deleted", 0);
        parameter.put("status", Collections.singletonList(QuotationStatusEnum.QUOTATION_3_QUOTED.getCode()));
        for (String inquiryGoodsId : inquiryGoodsIdList) {
            builder = new StringBuilder();
            builder.append("update\n")
                    .append(getTableName(ModelConst.T_INQUIRY_GOODS)).append("\n")
                    .append("set quote_count = \n")
                    .append("(select count(*) from\n")
                    .append(getTableName(ModelConst.T_QUOTATION_GOODS)).append("\n")
                    .append("where 1 = 1\n")
                    .append("and deleted = :deleted\n")
                    .append("and inquiry_goods_id = :inquiryGoodsId\n")
                    .append("and quotation_goods_status in (:status))\n")
                    .append("where id = :inquiryGoodsId\n");
            parameter.put("inquiryGoodsId", inquiryGoodsId);
            log.info("sql = {}, parameters = {}", builder, JSONObject.toJSONString(parameter));
            if (jdbcTemplate.update(builder.toString(), parameter) != 1) {
                result = false;
                break;
            }
        }
        return result;
    }

    /**
     * 获取报价商品id列表
     *
     * @param quotationIdSet        报价商品id集合
     * @param quotationGoodsDtoList 请求参数
     */
    private void getQuotationIdList(Set<String> quotationIdSet, List<QuotationGoodsDto> quotationGoodsDtoList) {
        Set<String> inquiryGoodsIdSet = Sets.newHashSet();
        // 获取用户信息
        UserDto user = UserUtils.getUserByUserId(RequestContext.getCorpLoginId());

        // 获取组织信息
        OrganizationDto org = OrgUtils.getOrgByOrgId(user.getOrganization_id().get(0).getId());

        quotationGoodsDtoList.forEach(quotation -> {
            SingleResponse<BOList> inquiryBOList = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY, "id", quotation.getInquiryId());
            if (!inquiryBOList.isSuccess() || inquiryBOList.getData().getTotal() == 0) {
                Exceptions.throwBizException(ErrorCodeEnum.BO_LIST_ERROR);
            }
            // 通过询价单号获取询价单信息，判断是不是整单报价
            if ("1".equals(String.valueOf(inquiryBOList.getData().getData().get(0).get("quote_total_strategy")))) {
                // 整单报价，查询询价单下所有询价商品
                SingleResponse<BOList> inquiryGoodsBOList = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY_GOODS, "inquiry_id", quotation.getInquiryId());
                if (!inquiryGoodsBOList.isSuccess() || inquiryGoodsBOList.getData().getTotal() == 0) {
                    Exceptions.throwBizException(ErrorCodeEnum.BO_LIST_ERROR);
                }
                inquiryGoodsBOList.getData().getData().forEach(inquiryGoodsMap -> inquiryGoodsIdSet.add(String.valueOf(inquiryGoodsMap.get("id"))));
                // 通过询价商品和报价供应商信息获取报价商品信息
                String[] columns = new String[]{"inquiry_goods_id", "vendor_organization_name"};
                Operator[] operators = new Operator[]{Operator.IN, Operator.EQ};
                Object[] columnsVal = new Object[]{inquiryGoodsIdSet, org.getName()};
                SingleResponse<BOList> quotationGoodsList = BoServiceUtils.findListByComplex(ModelConst.T_QUOTATION_GOODS, columns, columnsVal, operators);
                quotationGoodsList.getData().getData().forEach(quotationMap -> quotationIdSet.add(String.valueOf(quotationMap.get("id"))));
            } else {
                // 非整单报价，添加报价商品id
                quotationIdSet.add(quotation.getQuotationId());
            }
        });
    }

    /**
     * 将list集合转为in参数
     *
     * @param idList id集合
     * @return id字符串
     */
    private String getIdS(List<String> idList) {
        return idList.stream().map(String::valueOf).map(inquiryGoodsId -> "'" + inquiryGoodsId + "'")
                .collect(Collectors.joining(",", "(", ")"));
    }

    /**
     * 小规模供应商价格转换
     * @param quotationGoodsApprovedHistoryList    还价商品列表
     * @return  转化后的报价商品列表
     */
    public List<Map<String,Object>> conversion(List<Map<String, Object>> quotationGoodsApprovedHistoryList) {
        SingleResponse<BO> quotationGoodsBO;
        for (Map<String, Object> quotationGoodsApprovedHistory : quotationGoodsApprovedHistoryList) {
            // 通过报价商品id获取报价商品信息
            quotationGoodsBO = BoServiceUtils.loadBo(String.valueOf(quotationGoodsApprovedHistory.get("quotation_id")), ModelConst.T_QUOTATION_GOODS);
            // 只有采购税率字段不为空时才需要转换
            if (quotationGoodsBO.getData().getData().get("purchase_tax_rate") == null) {
                continue;
            }
            BigDecimal freight = quotationGoodsApprovedHistory.get("freight") == null ? BigDecimal.ZERO : (BigDecimal) quotationGoodsApprovedHistory.get("freight");
            BigDecimal purchaseTaxRate = (BigDecimal) quotationGoodsBO.getData().getData().get("purchase_tax_rate");

            // 根据未税单价和采购税率计算含税单价
            BigDecimal price = TaxRateUtils.calculateTaxAfter((BigDecimal) quotationGoodsApprovedHistory.get("pretax_price"), purchaseTaxRate);

            // 根据未税小计和采购税率计算含税小计
            BigDecimal total = TaxRateUtils.calculateTaxAfter((BigDecimal) quotationGoodsApprovedHistory.get("pretax_total"), purchaseTaxRate);

            // 小计需要四舍五入
            total = BigDecimalUtils.round(total, 2);

            // 计算税额，税额 = 含税小计 - 未税小计
            BigDecimal taxPayable = BigDecimalUtils.sub(total, (BigDecimal) quotationGoodsApprovedHistory.get("pretax_total"));

            // 计算含税总计，含税总计 = 含税小计 + 运费
            BigDecimal amount = BigDecimalUtils.add(total, freight);

            // 重新赋值
            quotationGoodsApprovedHistory.put("price", price);
            quotationGoodsApprovedHistory.put("total", total);
            quotationGoodsApprovedHistory.put("tax_payable", taxPayable);
            quotationGoodsApprovedHistory.put("amount", amount);
        }
        return quotationGoodsApprovedHistoryList;
    }

    /**
     * 判断供应商是否可以参与该询价商品的报价
     * @param org                   组织信息
     * @param inquiryGoodsIdList    询价商品
     */
    private boolean isItPossibleToParticipate(OrganizationDto org, List<String> inquiryGoodsIdList) {
        boolean result = false;

        // 是否是平台供应商
        if (org.getPlatform()) {
            result = true;
        } else {
            // 供应商是否开启仅邀请组织可报价
            boolean enabledInquiryInvited = OrgAttributeUtils.isEnabledAttribute(org.getId(), OrganizationAttributeEnum.INQUIRY_INVITED);
            if (!enabledInquiryInvited) {
                throw new BizException("供应商【" + org.getId() + "】非平台供应商,需开启仅邀请组织可报价属性");
            }
            List<String> customerIdList = OrgUtils.listCustomerByVendorId(org.getId());
            if (CollectionUtils.isEmpty(customerIdList)) {
                throw new BizException("供应商【" + org.getId() + "】暂未获得客户邀请");
            }
            List<String> customerIdAllList = Lists.newArrayList();
            for (String customerId : customerIdList) {
                // 获取当前客户组织的父组织信息
                String parentId = CollectionUtils.isEmpty(org.getParent_id()) ? customerId : org.getParent_id().get(0).getId();

                // 判断客户父组织是否开启了组织共享
                boolean enabledShareInviteVendors = OrgAttributeUtils.isEnabledAttribute(parentId, OrganizationAttributeEnum.SHARE_INVITE_VENDORS);
                if (enabledShareInviteVendors) {
                    List<String> customerListByParentId = OrgUtils.listCustomerByVendorId(parentId);
                    if (!CollectionUtils.isEmpty(customerListByParentId)) {
                        customerIdAllList.addAll(customerListByParentId);
                    }
                } else {
                    List<String> customerList = OrgUtils.listCustomerByVendorId(org.getId());
                    if (!CollectionUtils.isEmpty(customerList)) {
                        customerIdAllList.addAll(customerList);
                    }
                }
            }

            // 获取所选询价商品中可报价的询价商品
            StringBuilder sql = new StringBuilder();
            Map<String,Object> parameter = Maps.newHashMap();
            sql.append("select ig.* from \n");
            sql.append(getTableName(ModelConst.T_INQUIRY_GOODS)).append(" as ig \n");
            sql.append("left join ").append(getTableName(ModelConst.T_INQUIRY)).append(" as i on i.id = ig.inquiry_id and i.deleted = 0\n");
            sql.append("left join ").append(getTableName(ModelConst.T_INQUIRY_VENDOR)).append(" as iv on iv.inquiry_id = i.id and iv.deleted = 0\n");
            sql.append("where 1 = 1\n");
            sql.append("and ig.inquiry_goods_status = :inquiryGoodsStatus\n");
            sql.append("and ig.deleted = 0\n");
            sql.append("and ig.id in (:inquiryGoodsIdList)\n");
            // 询价方式为邀请，只有邀请的供应商才可以看到
            sql.append("and (i.vendor_scope = :vendorScope or iv.vendor_organization_id -> '$.id' = :vendorId)\n");
            sql.append("and CASE WHEN JSON_VALID( i.organization_id ) THEN JSON_UNQUOTE(i.organization_id -> '$.id') in (:customerIdList)\n");
            sql.append("ELSE NULL END\n");
            sql.append("group by ig.id\n");
            sql.append("order by ig.createdTime desc\n");
            parameter.put("inquiryGoodsStatus", InquiryStatusEnum.INQUIRY_GOODS_3_QUOTING.getCode());
            parameter.put("inquiryGoodsIdList", inquiryGoodsIdList);
            parameter.put("vendorScope", VendorScopeEnum.ALL.getCode());
            parameter.put("vendorId", org.getId());
            parameter.put("customerIdList", customerIdAllList);
            log.info("sql = {}, parameters = {}", sql, JSONObject.toJSONString(parameter));
            List<Map<String, Object>> inquiryGoodsList = jdbcTemplate.queryForList(sql.toString(), parameter);
            if (CollectionUtils.isEmpty(inquiryGoodsList)) {
                throw new BizException("供应商【" + org.getId() + "】仅可对邀请的客户进行报价");
            }
            if (inquiryGoodsList.size() == inquiryGoodsIdList.size()) {
                result = true;
            }
        }
        return result;
    }
}
